package com.qf.smartdevice.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.qf.smartdevice.dot.UserDto;
import com.qf.smartdevice.events.MyLoginEvent;
import com.qf.smartdevice.events.enums.CheckType;
import com.qf.smartdevice.events.enums.LoginResultEnum;
import com.qf.smartdevice.exception.AddDataException;
import com.qf.smartdevice.exception.ErrorCode;
import com.qf.smartdevice.exception.QueryDataException;
import com.qf.smartdevice.mapper.SysUserInfoMapper;
import com.qf.smartdevice.pojo.SysUserInfo;
import com.qf.smartdevice.service.SysUserInfoService;
import com.qf.smartdevice.utils.MD5Util;
import com.qf.smartdevice.utils.MyStringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.List;

/**
 * @author 王博康
 * @version 1.0
 * @project devicemanagementsystem
 * @description: TODO
 * @date 2022/3/14 21:49 星期一
 */
@Service
@Transactional
public class SysUserInfoServiceImpl implements SysUserInfoService {

    private Logger logger = LoggerFactory.getLogger(SysUserInfoServiceImpl.class);

    private SysUserInfoMapper sysUserInfoMapper;

    @Autowired
    public void setSysUserInfoMapper(SysUserInfoMapper sysUserInfoMapper) {
        this.sysUserInfoMapper = sysUserInfoMapper;
    }

    private ApplicationContext applicationContext;

    @Autowired
    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    @Override
    public SysUserInfo findById(Long userId) {
        return sysUserInfoMapper.findById(userId);
    }

    @Override
    public PageInfo<SysUserInfo> findAll(int pageSize, int pageNum) {
        PageHelper.startPage(pageNum,pageSize );
        List<SysUserInfo> userInfoList = sysUserInfoMapper.findAll();
        PageInfo<SysUserInfo> pageInfo = new PageInfo<>(userInfoList);
        return pageInfo;
    }

    @Override
    public void addUserInfo(SysUserInfo sysUserInfo) {
        //校验
        //1 判空
        Assert.isTrue(!sysUserInfo.isEmpty(CheckType.ADD),()->{
            throw new AddDataException("数据不能为空", ErrorCode.DATA_NULL);
        } );

        //2 校验格式
        Assert.isTrue(MyStringUtil.check(sysUserInfo.getPhone(),MyStringUtil.mobileRegex),()->{
            throw new AddDataException("手机格式不正确",ErrorCode.PHONE_REG_NOT_MACTH );
        });

        Assert.isTrue(MyStringUtil.check(sysUserInfo.getEmail(),MyStringUtil.emaiRegex ),()->{
            throw new AddDataException("邮箱格式不正确",ErrorCode.MAIL_REG_NOT_MACTH );
        } );

        //3 判断已存在用户
        //按照用户名查询一下
        SysUserInfo info = sysUserInfoMapper.findByUsername(sysUserInfo.getUsername());
        Assert.isNull(info, () -> {
            throw new AddDataException("用户名已存在", ErrorCode.USER_ALREADY_EXIST);
        });
        //按照手机号检查
        info = sysUserInfoMapper.findByPhone(sysUserInfo.getPhone());
        Assert.isNull(info, () -> {
            throw new AddDataException("手机号已存在", ErrorCode.PHONE_ALREADY_EXIST);
        });

        //按照邮箱检查
        info = sysUserInfoMapper.findByEmail(sysUserInfo.getEmail());
        Assert.isNull(info, () -> {
            throw new AddDataException("邮箱已存在", ErrorCode.EMAIL_ALREADY_EXIST);
        });

        //生成盐
        String salt = MD5Util.getRandomString(8);
        //生成密码
        String password = MD5Util.getMd5(sysUserInfo.getPassword(), salt, 1314);
        //存入数据
        sysUserInfo.setPwdSalt(salt);
        sysUserInfo.setPassword(password);

        //设置默认数据
        sysUserInfo.setCreateTime(new Date());
        //检查当前登录的用户,如果是管理员,设置管理员的信息,如果没有用户就是用户自己注册的
        sysUserInfo.setCreateBy(sysUserInfo.getUsername());
        sysUserInfo.setRemark("普通用户");
        //保存到数据库sysUserInfoMapper.addUserInfo(sysUserInfo);
        sysUserInfoMapper.addUserInfo(sysUserInfo);
        //日志打印
        logger.error("添加数据成功");

    }

    @Override
    public SysUserInfo findByUsername(String username) {
        return sysUserInfoMapper.findByUsername(username);
    }


    @Override
    public SysUserInfo findByPhone(String phone) {
        return sysUserInfoMapper.findByPhone(phone);
    }

    @Override
    public SysUserInfo findByEmail(String email) {
        return sysUserInfoMapper.findByEmail(email);
    }

    @Override
    public SysUserInfo login(UserDto userDto) {
        //判空
        Assert.isTrue(StringUtils.hasText(userDto.getUsername())&&StringUtils.hasText(userDto.getPassword()),()->{
            throw new QueryDataException("用户名或密码未输入",ErrorCode.USERS_PASSWORD_NULL);
        } );

        //查找账户是否存在
        SysUserInfo userInfo = sysUserInfoMapper.findByUsername(userDto.getUsername());
        Assert.notNull(userInfo,()->{
            throw new QueryDataException("用户名或密码错误",ErrorCode.USERS_PASSWORD_ERROR );
        } );

        //按原来的方式生成密码对比
        String salt = userInfo.getPwdSalt();
        String md5 = MD5Util.getMd5(userDto.getPassword(), salt, 1314);
        //断言密码正确，否则抛异常
        Assert.isTrue(md5.equalsIgnoreCase(userInfo.getPassword()),()->{
            //执行到这代表登录失败，需抛出登录事件（用来记录日志）和异常
            applicationContext.publishEvent(new MyLoginEvent(LoginResultEnum.FAIL,userDto.getUsername() ));
            throw new QueryDataException("用户名或密码错误",ErrorCode.USERS_PASSWORD_ERROR );
        } );

        //防止信息泄露到
        userInfo.setPwdSalt(null);
        userInfo.setPassword(null);

        //日志打印
        logger.error("登录成功");

        //抛出登录事件,用来记录日志
        applicationContext.publishEvent(new MyLoginEvent(LoginResultEnum.SUCCESS,userDto.getUsername() ));

        return userInfo;
    }






}
